Rework of GtkFileChooserButton, some cleanups. Fixes #154388, #154390,
authorJames M. Cape <jcape@ignore-your.tv>
Tue, 26 Oct 2004 04:29:56 +0000 (04:29 +0000)
committerJames M. Cape <jcape@src.gnome.org>
Tue, 26 Oct 2004 04:29:56 +0000 (04:29 +0000)
2004-10-25  James M. Cape  <jcape@ignore-your.tv>

Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
#154390, #154390, #156272.

* docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
below GtkFileChooser.
* docs/reference/gtk/gtk-sections.txt: Added
gtk_file_chooser_button_get_width_chars(),
gtk_file_chooser_button_set_width_chars(),
gtk_label_set_width_chars(), gtk_label_get_width_chars().
* docs/reference/gtk/gtk.types: Added
gtk_cell_renderer_combo_get_type,
gtk_cell_view_get_type,
gtk_text_iter_get_type.
* docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
"logo-icon-name" property.
* docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for
properties
(b/c of get_type() inclusion above).
* docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
* docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars"
property,
getters/setters.
* docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
* gtk/gtkentrycompletion.c:
(_gtk_entry_completion_popdown): Don't show if the entry isn't
mapped.
* gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
rewritten, adds "width-chars" property, icons, working save
modes, volume/Home/Desktop friendly-naming support.
* gtk/gtklabel.[c,h]:
(gtk_label_class_init), (gtk_label_init),
(gtk_label_get_property), (gtk_label_set_property),
(gtk_label_get_width_chars), (gtk_label_set_width_chars),
(gtk_label_size_request): Add "width-chars" property.
* tests/testfilechooserbutton.c: Update, use 4 different buttons
for the different ACTIONs.
* gtk/.cvsignore: Ignore gtk-update-icon-cache.
* tests/.cvsignore: Ignore testimage.

20 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/gtk/gtk-docs.sgml
docs/reference/gtk/gtk-sections.txt
docs/reference/gtk/gtk.types
docs/reference/gtk/tmpl/gtkaboutdialog.sgml
docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml [new file with mode: 0644]
docs/reference/gtk/tmpl/gtkcellview.sgml
docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml
docs/reference/gtk/tmpl/gtklabel.sgml
gtk/.cvsignore
gtk/gtkentrycompletion.c
gtk/gtkfilechooserbutton.c
gtk/gtkfilechooserbutton.h
gtk/gtklabel.c
gtk/gtklabel.h
tests/.cvsignore
tests/testfilechooserbutton.c

index bc0600b659de5279421420b9bc6395f41743ced4..eba389232b1472471ad0bc101a9ec0725fce327f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2004-10-25  James M. Cape  <jcape@ignore-your.tv>
+
+       Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+       #154390, #154390, #156272.
+
+       * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+       below GtkFileChooser.
+       * docs/reference/gtk/gtk-sections.txt: Added
+       gtk_file_chooser_button_get_width_chars(),
+       gtk_file_chooser_button_set_width_chars(),
+       gtk_label_set_width_chars(), gtk_label_get_width_chars().
+       * docs/reference/gtk/gtk.types: Added
+       gtk_cell_renderer_combo_get_type,
+       gtk_cell_view_get_type,
+       gtk_text_iter_get_type.
+       * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+       "logo-icon-name" property.
+       * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+       (b/c of get_type() inclusion above).
+       * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+       * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+       getters/setters.
+       * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+       * gtk/gtkentrycompletion.c:
+       (_gtk_entry_completion_popdown): Don't show if the entry isn't
+       mapped.
+       * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+       rewritten, adds "width-chars" property, icons, working save modes,
+       volume/Home/Desktop friendly-naming support.
+       * gtk/gtklabel.[c,h]:
+       (gtk_label_class_init), (gtk_label_init),
+       (gtk_label_get_property), (gtk_label_set_property),
+       (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+       (gtk_label_size_request): Add "width-chars" property.
+       * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+       the different ACTIONs.
+       * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+       * tests/.cvsignore: Ignore testimage.
+
 2004-10-25  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
index bc0600b659de5279421420b9bc6395f41743ced4..eba389232b1472471ad0bc101a9ec0725fce327f 100644 (file)
@@ -1,3 +1,42 @@
+2004-10-25  James M. Cape  <jcape@ignore-your.tv>
+
+       Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+       #154390, #154390, #156272.
+
+       * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+       below GtkFileChooser.
+       * docs/reference/gtk/gtk-sections.txt: Added
+       gtk_file_chooser_button_get_width_chars(),
+       gtk_file_chooser_button_set_width_chars(),
+       gtk_label_set_width_chars(), gtk_label_get_width_chars().
+       * docs/reference/gtk/gtk.types: Added
+       gtk_cell_renderer_combo_get_type,
+       gtk_cell_view_get_type,
+       gtk_text_iter_get_type.
+       * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+       "logo-icon-name" property.
+       * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+       (b/c of get_type() inclusion above).
+       * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+       * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+       getters/setters.
+       * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+       * gtk/gtkentrycompletion.c:
+       (_gtk_entry_completion_popdown): Don't show if the entry isn't
+       mapped.
+       * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+       rewritten, adds "width-chars" property, icons, working save modes,
+       volume/Home/Desktop friendly-naming support.
+       * gtk/gtklabel.[c,h]:
+       (gtk_label_class_init), (gtk_label_init),
+       (gtk_label_get_property), (gtk_label_set_property),
+       (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+       (gtk_label_size_request): Add "width-chars" property.
+       * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+       the different ACTIONs.
+       * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+       * tests/.cvsignore: Ignore testimage.
+
 2004-10-25  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
index bc0600b659de5279421420b9bc6395f41743ced4..eba389232b1472471ad0bc101a9ec0725fce327f 100644 (file)
@@ -1,3 +1,42 @@
+2004-10-25  James M. Cape  <jcape@ignore-your.tv>
+
+       Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+       #154390, #154390, #156272.
+
+       * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+       below GtkFileChooser.
+       * docs/reference/gtk/gtk-sections.txt: Added
+       gtk_file_chooser_button_get_width_chars(),
+       gtk_file_chooser_button_set_width_chars(),
+       gtk_label_set_width_chars(), gtk_label_get_width_chars().
+       * docs/reference/gtk/gtk.types: Added
+       gtk_cell_renderer_combo_get_type,
+       gtk_cell_view_get_type,
+       gtk_text_iter_get_type.
+       * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+       "logo-icon-name" property.
+       * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+       (b/c of get_type() inclusion above).
+       * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+       * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+       getters/setters.
+       * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+       * gtk/gtkentrycompletion.c:
+       (_gtk_entry_completion_popdown): Don't show if the entry isn't
+       mapped.
+       * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+       rewritten, adds "width-chars" property, icons, working save modes,
+       volume/Home/Desktop friendly-naming support.
+       * gtk/gtklabel.[c,h]:
+       (gtk_label_class_init), (gtk_label_init),
+       (gtk_label_get_property), (gtk_label_set_property),
+       (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+       (gtk_label_size_request): Add "width-chars" property.
+       * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+       the different ACTIONs.
+       * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+       * tests/.cvsignore: Ignore testimage.
+
 2004-10-25  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
index bc0600b659de5279421420b9bc6395f41743ced4..eba389232b1472471ad0bc101a9ec0725fce327f 100644 (file)
@@ -1,3 +1,42 @@
+2004-10-25  James M. Cape  <jcape@ignore-your.tv>
+
+       Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+       #154390, #154390, #156272.
+
+       * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+       below GtkFileChooser.
+       * docs/reference/gtk/gtk-sections.txt: Added
+       gtk_file_chooser_button_get_width_chars(),
+       gtk_file_chooser_button_set_width_chars(),
+       gtk_label_set_width_chars(), gtk_label_get_width_chars().
+       * docs/reference/gtk/gtk.types: Added
+       gtk_cell_renderer_combo_get_type,
+       gtk_cell_view_get_type,
+       gtk_text_iter_get_type.
+       * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+       "logo-icon-name" property.
+       * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+       (b/c of get_type() inclusion above).
+       * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+       * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+       getters/setters.
+       * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+       * gtk/gtkentrycompletion.c:
+       (_gtk_entry_completion_popdown): Don't show if the entry isn't
+       mapped.
+       * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+       rewritten, adds "width-chars" property, icons, working save modes,
+       volume/Home/Desktop friendly-naming support.
+       * gtk/gtklabel.[c,h]:
+       (gtk_label_class_init), (gtk_label_init),
+       (gtk_label_get_property), (gtk_label_set_property),
+       (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+       (gtk_label_size_request): Add "width-chars" property.
+       * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+       the different ACTIONs.
+       * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+       * tests/.cvsignore: Ignore testimage.
+
 2004-10-25  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
index 462afea8a5043049348b1cdca8cf271f2970aa24..81cdb87c10b1f872ec576eb5505ca8dac04fb037 100644 (file)
@@ -444,8 +444,8 @@ that is, GUI components such as <link linkend="GtkButton">GtkButton</link> or
         &GtkColorSelection;
         &GtkColorSelectionDialog;
         &GtkFileSelection;
-       &GtkFileChooserButton;
        &GtkFileChooser;
+       &GtkFileChooserButton;
        &GtkFileChooserDialog;
        &GtkFileChooserWidget;
        &GtkFileFilter;
@@ -599,5 +599,3 @@ that is, GUI components such as <link linkend="GtkButton">GtkButton</link> or
   </index>  
 
 </book>
-
-
index 26aed249356fac18fe7c8af6d6b84c9f8b945a52..c8d165dca890e66e7e192888c4c924c50229c33b 100644 (file)
@@ -1285,6 +1285,8 @@ gtk_file_chooser_button_get_title
 gtk_file_chooser_button_set_title
 gtk_file_chooser_button_get_active
 gtk_file_chooser_button_set_active
+gtk_file_chooser_button_get_width_chars
+gtk_file_chooser_button_set_width_chars
 <SUBSECTION Standard>
 GTK_FILE_CHOOSER_BUTTON
 GTK_IS_FILE_CHOOSER_BUTTON
@@ -1903,6 +1905,7 @@ gtk_label_set_markup_with_mnemonic
 gtk_label_set_pattern
 gtk_label_set_justify
 gtk_label_set_ellipsize
+gtk_label_set_width_chars
 gtk_label_get
 gtk_label_parse_uline
 gtk_label_set_line_wrap
@@ -1919,6 +1922,7 @@ gtk_label_set_text_with_mnemonic
 gtk_label_get_attributes
 gtk_label_get_justify
 gtk_label_get_ellipsize
+gtk_label_get_width_chars
 gtk_label_get_label
 gtk_label_get_layout
 gtk_label_get_line_wrap
@@ -5532,4 +5536,3 @@ gtk_icon_factory_get_type
 gtk_icon_set_get_type
 gtk_icon_source_get_type
 </SECTION>
-
index d983e187254334eafb44ccfc3b929fb4aaa49e43..f0b2561ed1602c0e953e27562debd1f43f618c71 100644 (file)
@@ -18,10 +18,12 @@ gtk_button_get_type
 gtk_calendar_get_type
 gtk_cell_layout_get_type
 gtk_cell_renderer_get_type
+gtk_cell_renderer_combo_get_type
 gtk_cell_renderer_pixbuf_get_type
 gtk_cell_renderer_text_get_type
 gtk_cell_renderer_toggle_get_type
 gtk_cell_renderer_progress_get_type
+gtk_cell_view_get_type
 gtk_check_button_get_type
 gtk_check_menu_item_get_type
 gtk_clist_get_type
@@ -118,6 +120,7 @@ gtk_tearoff_menu_item_get_type
 gtk_text_buffer_get_type
 gtk_text_child_anchor_get_type
 gtk_text_get_type
+gtk_text_iter_get_type
 gtk_text_mark_get_type
 gtk_text_tag_get_type
 gtk_text_tag_table_get_type
index 1f7dd84dc94721228224692bc01cbbd4233a205e..284e4491c4d631e95a6053e3538e64c43245972e 100644 (file)
@@ -67,6 +67,11 @@ only private fields and should not be directly accessed.
 
 </para>
 
+<!-- ##### ARG GtkAboutDialog:logo-icon-name ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GtkAboutDialog:name ##### -->
 <para>
 
diff --git a/docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml b/docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml
new file mode 100644 (file)
index 0000000..e0353c1
--- /dev/null
@@ -0,0 +1,45 @@
+<!-- ##### SECTION Title ##### -->
+GtkCellRendererCombo
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### STRUCT GtkCellRendererCombo ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkCellRendererCombo:has-entry ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellRendererCombo:model ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellRendererCombo:text-column ##### -->
+<para>
+
+</para>
+
+<!-- ##### FUNCTION gtk_cell_renderer_combo_new ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
+
index 24c388ca389d5c76b781ecf40acc68ea47230d59..ec0072bce6b04cb42f0ee48678a5b5567c69dbb6 100644 (file)
@@ -19,7 +19,21 @@ A widget displaying a single row of a GtkTreeModel
 
 </para>
 
-@parent_instance: 
+
+<!-- ##### ARG GtkCellView:background ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellView:background-gdk ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellView:background-set ##### -->
+<para>
+
+</para>
 
 <!-- ##### FUNCTION gtk_cell_view_new ##### -->
 <para>
index 09c476c01c781bc55fb78b98154bfe2e7f22e300..3c03093237eb4c6ca29fe1c8b040fd29b5ec59a7 100644 (file)
@@ -57,8 +57,9 @@ look like a #GtkButton.
 <important>
 <para>
 The #GtkFileChooserButton will ellipsize the label while in Open mode,
-and thus will thus request little horizontal space.  To give the dialog
-more space, you should call gtk_widget_size_request(), or pack it in
+and thus will thus request little horizontal space.  To give the button
+more space, you should call gtk_widget_size_request(),
+gtk_file_chooser_button_set_width_chars (), or pack the button in
 such a way that other interface elements give space to the widget.
 </para>
 </important>
@@ -91,6 +92,11 @@ Instance of the #GtkFileChooserDialog associated with the button.
 Title to put on the #GtkFileChooserDialog associated with the button.
 </para>
 
+<!-- ##### ARG GtkFileChooserButton:width-chars ##### -->
+<para>
+The width of the entry and label inside the button, in characters.
+</para>
+
 <!-- ##### FUNCTION gtk_file_chooser_button_new ##### -->
 <para>
 
@@ -155,3 +161,21 @@ Title to put on the #GtkFileChooserDialog associated with the button.
 @is_active: 
 
 
+<!-- ##### FUNCTION gtk_file_chooser_button_get_width_chars ##### -->
+<para>
+
+</para>
+
+@button: 
+@Returns: 
+
+
+<!-- ##### FUNCTION gtk_file_chooser_button_set_width_chars ##### -->
+<para>
+
+</para>
+
+@button: 
+@n_chars: 
+
+
index a58a43fbe2616689a30dc244a51ba0f8893e15e4..4d9c108f84b240af22118384953265a83af425be 100644 (file)
@@ -230,6 +230,11 @@ described below.
 
 </para>
 
+<!-- ##### ARG GtkLabel:width-chars ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GtkLabel:wrap ##### -->
 <para>
 
@@ -310,6 +315,15 @@ The pattern of underlines you want under the existing text within the
 @mode: 
 
 
+<!-- ##### FUNCTION gtk_label_set_width_chars ##### -->
+<para>
+
+</para>
+
+@label: 
+@n_chars: 
+
+
 <!-- ##### FUNCTION gtk_label_get ##### -->
 <para>
 Gets the current string of text within the #GtkLabel and writes it to
@@ -462,6 +476,15 @@ Gtk+ 1.0.x.
 @Returns: 
 
 
+<!-- ##### FUNCTION gtk_label_get_width_chars ##### -->
+<para>
+
+</para>
+
+@label: 
+@Returns: 
+
+
 <!-- ##### FUNCTION gtk_label_get_label ##### -->
 <para>
 
index 2407e9490d8cda86414bb2e1eab9210b16728234..0eb579021e8db2122236b33e1788059d0b08c633 100644 (file)
@@ -24,3 +24,4 @@ stamp-gtkmarshalers.h
 gtk-query-immodules-2.0
 .saved
 gtkalias.h
+gtk-update-icon-cache
index 089fb76534b8e39e4b3f061cc39f1738e3544120..689debb8f9d9dc4980a064c7ca9b562006476563 100644 (file)
@@ -1258,7 +1258,10 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion)
   GtkTreePath *path;
   gboolean above;
   gint width;
-  
+
+  if (!completion->priv->entry->window)
+    return FALSE;
+
   gdk_window_get_origin (completion->priv->entry->window, &x, &y);
   _gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
 
@@ -1343,6 +1346,9 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion)
   if (GTK_WIDGET_MAPPED (completion->priv->popup_window))
     return;
 
+  if (!GTK_WIDGET_MAPPED (completion->priv->entry))
+    return;
+
   completion->priv->ignore_enter = TRUE;
     
   column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
@@ -1358,7 +1364,7 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion)
   _gtk_entry_completion_resize_popup (completion);
 
   gtk_widget_show (completion->priv->popup_window);
-
+    
   gtk_grab_add (completion->priv->popup_window);
   gdk_pointer_grab (completion->priv->popup_window->window, TRUE,
                     GDK_BUTTON_PRESS_MASK |
index 5ebdac05b503f2ab4b5fad4e38cfb279aa766313..3c262df93b79725947c7e1d4284af7a328d706cd 100644 (file)
 #define GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE(object) (GTK_FILE_CHOOSER_BUTTON ((object))->priv)
 
 #define DEFAULT_FILENAME       N_("(None)")
-#define DEFAULT_SPACING                0
+#define MIN_LABEL_WIDTH                100
+#define ENTRY_BUTTON_SPACING   0
+#define FALLBACK_ICON_SIZE     20
+#define FALLBACK_ICON_NAME     "stock_unknown"
+#define NEW_FILE_ICON_NAME     "stock_new"
+#define NEW_DIR_ICON_NAME      "stock_new-dir"
 
 /* ********************** *
  *  Private Enumerations  *
@@ -69,7 +74,8 @@ enum
 
   PROP_DIALOG,
   PROP_TITLE,
-  PROP_ACTIVE
+  PROP_ACTIVE,
+  PROP_WIDTH_CHARS
 };
 
 
@@ -80,17 +86,24 @@ enum
 struct _GtkFileChooserButtonPrivate
 {
   GtkWidget *dialog;
+  GtkWidget *accept_button;
+  GtkWidget *entry_box;
+  GtkWidget *entry_image;
   GtkWidget *entry;
+  GtkWidget *label_box;
+  GtkWidget *label_image;
   GtkWidget *label;
-  GtkWidget *separator;
   GtkWidget *button;
 
-  gchar *filesystem;
+  gchar *backend;
   gulong entry_changed_id;
   gulong dialog_file_activated_id;
   gulong dialog_folder_changed_id;
   gulong dialog_selection_changed_id;
+  gulong dialog_selection_changed_proxy_id;
+  gulong settings_signal_id;
   guint update_id;
+  gint icon_size;
 };
 
 
@@ -109,12 +122,15 @@ enum
  * ********************* */
 
 /* GObject Functions */
+static GObject *gtk_file_chooser_button_constructor        (GType             type,
+                                                           guint             n_params,
+                                                           GObjectConstructParam *params);
 static void     gtk_file_chooser_button_set_property       (GObject          *object,
-                                                           guint             id,
+                                                           guint             param_id,
                                                            const GValue     *value,
                                                            GParamSpec       *pspec);
 static void     gtk_file_chooser_button_get_property       (GObject          *object,
-                                                           guint             id,
+                                                           guint             param_id,
                                                            GValue           *value,
                                                            GParamSpec       *pspec);
 
@@ -131,14 +147,22 @@ static void     gtk_file_chooser_button_drag_data_received (GtkWidget        *wi
                                                            guint             drag_time);
 static void     gtk_file_chooser_button_show_all           (GtkWidget        *widget);
 static void     gtk_file_chooser_button_hide_all           (GtkWidget        *widget);
+static void     gtk_file_chooser_button_show               (GtkWidget        *widget);
+static void     gtk_file_chooser_button_hide               (GtkWidget        *widget);
 static gboolean gtk_file_chooser_button_mnemonic_activate  (GtkWidget        *widget,
                                                            gboolean          group_cycling);
+static void     gtk_file_chooser_button_style_set          (GtkWidget        *widget,
+                                                           GtkStyle         *old_style);
+static void     gtk_file_chooser_button_screen_changed     (GtkWidget        *widget,
+                                                           GdkScreen        *old_screen);
 
 /* Child Widget Callbacks */
 static void     dialog_update_preview_cb                   (GtkFileChooser   *dialog,
                                                            gpointer          user_data);
 static void     dialog_selection_changed_cb                (GtkFileChooser   *dialog,
                                                            gpointer          user_data);
+static void     dialog_selection_changed_proxy_cb          (GtkFileChooser   *dialog,
+                                                           gpointer          user_data);
 static void     dialog_file_activated_cb                   (GtkFileChooser   *dialog,
                                                            gpointer          user_data);
 static void     dialog_current_folder_changed_cb           (GtkFileChooser   *dialog,
@@ -162,16 +186,17 @@ static void     button_notify_active_cb                    (GObject          *re
 static void     entry_size_allocate_cb                     (GtkWidget        *entry,
                                                            GtkAllocation    *allocation,
                                                            gpointer          user_data);
-static void     entry_changed_cb                           (GtkEditable      *chooser_entry,
+static void     entry_changed_cb                           (GtkEditable      *editable,
                                                            gpointer          user_data);
 
 /* Utility Functions */
-static void     gtk_file_chooser_button_set_dialog         (GObject          *object,
-                                                           GtkWidget        *dialog);
+static void     remove_settings_signal                     (GtkFileChooserButton *button,
+                                                           GdkScreen            *screen);
 
-static gboolean update_dialog                              (gpointer          user_data);
-static gboolean update_dialog_idle                         (gpointer          user_data);
+static void     update_dialog                              (GtkFileChooserButton *button);
 static void     update_entry                               (GtkFileChooserButton *button);
+static void     update_label                               (GtkFileChooserButton *button);
+static void     update_icons                               (GtkFileChooserButton *button);
 
 
 /* ******************* *
@@ -198,6 +223,7 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
   gtkobject_class = GTK_OBJECT_CLASS (class);
   widget_class = GTK_WIDGET_CLASS (class);
 
+  gobject_class->constructor = gtk_file_chooser_button_constructor;
   gobject_class->set_property = gtk_file_chooser_button_set_property;
   gobject_class->get_property = gtk_file_chooser_button_get_property;
 
@@ -206,6 +232,10 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
   widget_class->drag_data_received = gtk_file_chooser_button_drag_data_received;
   widget_class->show_all = gtk_file_chooser_button_show_all;
   widget_class->hide_all = gtk_file_chooser_button_hide_all;
+  widget_class->show = gtk_file_chooser_button_show;
+  widget_class->hide = gtk_file_chooser_button_hide;
+  widget_class->style_set = gtk_file_chooser_button_style_set;
+  widget_class->screen_changed = gtk_file_chooser_button_screen_changed;
   widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
 
   g_object_class_install_property (gobject_class, PROP_DIALOG,
@@ -226,6 +256,12 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
                                                         P_("Active"),
                                                         P_("Whether the browse dialog is visible or not."),
                                                         FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_WIDTH_CHARS,
+                                  g_param_spec_int ("width-chars",
+                                                    P_("Width In Characters"),
+                                                    P_("The desired width of the button widget, in characters."),
+                                                    -1, G_MAXINT, -1,
+                                                    G_PARAM_READWRITE));
 
   _gtk_file_chooser_install_properties (gobject_class);
 
@@ -237,18 +273,29 @@ static void
 gtk_file_chooser_button_init (GtkFileChooserButton *button)
 {
   GtkFileChooserButtonPrivate *priv;
-  GtkWidget *box, *image;
+  GtkWidget *box, *image, *sep;
 
-  gtk_box_set_spacing (GTK_BOX (button), DEFAULT_SPACING);
+  gtk_box_set_spacing (GTK_BOX (button), ENTRY_BUTTON_SPACING);
 
   priv = G_TYPE_INSTANCE_GET_PRIVATE (button, GTK_TYPE_FILE_CHOOSER_BUTTON,
                                      GtkFileChooserButtonPrivate);
   button->priv = priv;
 
+  priv->icon_size = FALLBACK_ICON_SIZE;
+
   gtk_widget_push_composite_child ();
 
+  priv->entry_box = gtk_hbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (button), priv->entry_box);
+
+  priv->entry_image = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (priv->entry_box), priv->entry_image,
+                     FALSE, FALSE, 0);
+  gtk_widget_show (priv->entry_image);
+
   priv->entry = _gtk_file_chooser_entry_new (FALSE);
-  gtk_container_add (GTK_CONTAINER (button), priv->entry);
+  gtk_container_add (GTK_CONTAINER (priv->entry_box), priv->entry);
+  gtk_widget_show (priv->entry);
 
   priv->button = gtk_toggle_button_new ();
   g_signal_connect (priv->button, "toggled",
@@ -263,22 +310,31 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
   box = gtk_hbox_new (FALSE, 4);
   gtk_container_add (GTK_CONTAINER (priv->button), box);
   gtk_widget_show (box);
+  
+  priv->label_box = gtk_hbox_new (FALSE, 6);
+  gtk_container_add (GTK_CONTAINER (box), priv->label_box);
+  gtk_widget_show (priv->label_box);
+
+  priv->label_image = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (priv->label_box), priv->label_image,
+                     FALSE, FALSE, 0);
+  gtk_widget_show (priv->label_image);
 
   priv->label = gtk_label_new (_(DEFAULT_FILENAME));
   gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_START);
   gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 2);
+  gtk_container_add (GTK_CONTAINER (priv->label_box), priv->label);
   gtk_widget_show (priv->label);
 
+  sep = gtk_vseparator_new ();
+  gtk_box_pack_end (GTK_BOX (priv->label_box), sep, FALSE, FALSE, 0);
+  gtk_widget_show (sep);
+
   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
                                    GTK_ICON_SIZE_SMALL_TOOLBAR);
   gtk_box_pack_end (GTK_BOX (box), image, FALSE, FALSE, 0);
   gtk_widget_show (image);
 
-  priv->separator = gtk_vseparator_new ();
-  gtk_box_pack_end (GTK_BOX (box), priv->separator, FALSE, FALSE, 0);
-  gtk_widget_show (priv->separator);
-
   gtk_widget_pop_composite_child ();
 
   /* DnD */
@@ -297,10 +353,92 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
  *  GObject Functions  *
  * ******************* */
 
+static GObject *
+gtk_file_chooser_button_constructor (GType                  type,
+                                    guint                  n_params,
+                                    GObjectConstructParam *params)
+{
+  GObject *object;
+  GtkFileChooserButtonPrivate *priv;
+  GtkFilePath *path;
+
+  object = (*G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->constructor) (type,
+                                                                                 n_params,
+                                                                                 params);
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+
+  if (!priv->dialog)
+    {
+      if (priv->backend)
+       priv->dialog = gtk_file_chooser_dialog_new_with_backend (NULL, NULL,
+                                                                GTK_FILE_CHOOSER_ACTION_OPEN,
+                                                                priv->backend, NULL);
+      else
+       priv->dialog = gtk_file_chooser_dialog_new (NULL, NULL,
+                                                   GTK_FILE_CHOOSER_ACTION_OPEN,
+                                                   NULL);
+
+      gtk_dialog_add_button (GTK_DIALOG (priv->dialog),
+                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+      priv->accept_button = gtk_dialog_add_button (GTK_DIALOG (priv->dialog),
+                                                  GTK_STOCK_OPEN,
+                                                  GTK_RESPONSE_ACCEPT);
+      gtk_dialog_set_default_response (GTK_DIALOG (priv->dialog),
+                                      GTK_RESPONSE_ACCEPT);
+
+      gtk_dialog_set_alternative_button_order (GTK_DIALOG (priv->dialog),
+                                              GTK_RESPONSE_ACCEPT,
+                                              GTK_RESPONSE_CANCEL,
+                                              -1);
+    }
+
+  g_free (priv->backend);
+  priv->backend = NULL;
+
+  g_signal_connect (priv->dialog, "delete-event",
+                   G_CALLBACK (dialog_delete_event_cb), object);
+  g_signal_connect (priv->dialog, "response",
+                   G_CALLBACK (dialog_response_cb), object);
+
+  /* This is used, instead of the standard delegate, to ensure that signals are only
+   * delegated when the OK button is pressed. */
+  g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, priv->dialog);
+  priv->dialog_folder_changed_id =
+    g_signal_connect (priv->dialog, "current-folder-changed",
+                     G_CALLBACK (dialog_current_folder_changed_cb), object);
+  priv->dialog_file_activated_id =
+    g_signal_connect (priv->dialog, "file-activated",
+                     G_CALLBACK (dialog_file_activated_cb), object);
+  priv->dialog_selection_changed_id =
+    g_signal_connect (priv->dialog, "selection-changed",
+                     G_CALLBACK (dialog_selection_changed_cb), object);
+  priv->dialog_selection_changed_proxy_id =
+    g_signal_connect (priv->dialog, "selection-changed",
+                     G_CALLBACK (dialog_selection_changed_proxy_cb), object);
+  g_signal_connect (priv->dialog, "update-preview",
+                   G_CALLBACK (dialog_update_preview_cb), object);
+  g_signal_connect (priv->dialog, "notify",
+                   G_CALLBACK (dialog_notify_cb), object);
+  g_object_add_weak_pointer (G_OBJECT (priv->dialog),
+                            (gpointer *) (&priv->dialog));
+
+  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+                                          _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog)));
+  path = gtk_file_path_new_steal ("/");
+  _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+                                          path);
+  priv->entry_changed_id = g_signal_connect (priv->entry, "changed",
+                                            G_CALLBACK (entry_changed_cb),
+                                            object);
+
+  update_label (GTK_FILE_CHOOSER_BUTTON (object));
+
+  return object;
+}
 
 static void
 gtk_file_chooser_button_set_property (GObject      *object,
-                                     guint         id,
+                                     guint         param_id,
                                      const GValue *value,
                                      GParamSpec   *pspec)
 {
@@ -308,39 +446,26 @@ gtk_file_chooser_button_set_property (GObject      *object,
 
   priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
 
-  switch (id)
+  switch (param_id)
     {
     case PROP_DIALOG:
-      {
-       GtkWidget *widget;
-
-       widget = g_value_get_object (value);
-
-       if (widget == NULL)
-         {
-           widget = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
-                                  "file-system-backend", priv->filesystem, NULL);
-           g_free (priv->filesystem);
-           priv->filesystem = NULL;
-
-           gtk_dialog_add_button (GTK_DIALOG (widget),
-                                  GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
-           gtk_dialog_add_button (GTK_DIALOG (widget),
-                                  GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
-         }
-
-       gtk_file_chooser_button_set_dialog (object, widget);
-      }
+      /* Construct-only */
+      priv->dialog = g_value_get_object (value);
       break;
     case PROP_ACTIVE:
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button),
                                    g_value_get_boolean (value));
       break;
+    case PROP_WIDTH_CHARS:
+      gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (object),
+                                              g_value_get_int (value));
+      break;
 
     case GTK_FILE_CHOOSER_PROP_ACTION:
       g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
-      _gtk_file_chooser_entry_set_action (priv->entry, 
-                                         (GtkFileChooserAction)g_value_get_enum (value));
+      _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+                                         (GtkFileChooserAction) g_value_get_enum (value));
+      update_icons (GTK_FILE_CHOOSER_BUTTON (object));
 
       switch (g_value_get_enum (value))
        {
@@ -348,22 +473,24 @@ gtk_file_chooser_button_set_property (GObject      *object,
          gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
          /* Fall through to set the widget states */
        case GTK_FILE_CHOOSER_ACTION_OPEN:
-         gtk_widget_hide (priv->entry);
-         gtk_widget_show (priv->label);
-         gtk_widget_show (priv->separator);
+         gtk_widget_hide (priv->entry_box);
+         gtk_widget_show (priv->label_box);
          gtk_box_set_child_packing (GTK_BOX (object), priv->button,
                                     TRUE, TRUE, 0, GTK_PACK_START);
+         gtk_button_set_label (GTK_BUTTON (priv->accept_button),
+                               GTK_STOCK_OPEN);
          break;
 
        case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
          gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
          /* Fall through to set the widget states */
        case GTK_FILE_CHOOSER_ACTION_SAVE:
-         gtk_widget_show (priv->entry);
-         gtk_widget_hide (priv->label);
-         gtk_widget_hide (priv->separator);
+         gtk_widget_show (priv->entry_box);
+         gtk_widget_hide (priv->label_box);
          gtk_box_set_child_packing (GTK_BOX (object), priv->button,
                                     FALSE, FALSE, 0, GTK_PACK_START);
+         gtk_button_set_label (GTK_BUTTON (priv->accept_button),
+                               GTK_STOCK_SAVE);
          break;
        }
       break;
@@ -381,7 +508,7 @@ gtk_file_chooser_button_set_property (GObject      *object,
 
     case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
       /* Construct-only */
-      priv->filesystem = g_value_dup_string (value);
+      priv->backend = g_value_dup_string (value);
       break;
 
     case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
@@ -389,24 +516,30 @@ gtk_file_chooser_button_set_property (GObject      *object,
                 G_STRFUNC, G_OBJECT_TYPE_NAME (object));
       break;
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
     }
 }
 
-
 static void
 gtk_file_chooser_button_get_property (GObject    *object,
-                                     guint       id,
+                                     guint       param_id,
                                      GValue     *value,
                                      GParamSpec *pspec)
 {
-  GtkFileChooserButtonPrivate *priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+  GtkFileChooserButtonPrivate *priv;
 
-  switch (id)
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+
+  switch (param_id)
     {
     case PROP_ACTIVE:
-      g_value_set_boolean (value, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)));
+      g_value_set_boolean (value,
+                          gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)));
+      break;
+    case PROP_WIDTH_CHARS:
+      g_value_set_int (value,
+                      gtk_entry_get_width_chars (GTK_ENTRY (priv->entry)));
       break;
 
     case PROP_TITLE:
@@ -424,7 +557,7 @@ gtk_file_chooser_button_get_property (GObject    *object,
       break;
 
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
     }
 }
@@ -441,11 +574,14 @@ gtk_file_chooser_button_destroy (GtkObject * object)
 
   priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
 
+  if (priv->update_id)
+    g_source_remove (priv->update_id);
+
   if (priv->dialog != NULL)
     gtk_widget_destroy (priv->dialog);
   
-  if (priv->update_id != 0)
-    g_source_remove (priv->update_id);
+  remove_settings_signal (GTK_FILE_CHOOSER_BUTTON (object),
+                         gtk_widget_get_screen (GTK_WIDGET (object)));
 
   if (GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy != NULL)
     (*GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy) (object);
@@ -494,7 +630,6 @@ gtk_file_chooser_button_drag_data_received (GtkWidget            *widget,
          break;
 
        selected = FALSE;
-       g_signal_handler_block (priv->entry, priv->entry_changed_id);
        for (i = 0; !selected && uris[i] != NULL; i++)
          {
            GtkFileSystem *fs;
@@ -542,7 +677,6 @@ gtk_file_chooser_button_drag_data_received (GtkWidget            *widget,
 
            gtk_file_path_free (path);
          }
-       g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
 
        g_strfreev (uris);
       }
@@ -558,44 +692,151 @@ gtk_file_chooser_button_drag_data_received (GtkWidget         *widget,
   gtk_drag_finish (context, TRUE, FALSE, drag_time);
 }
 
-
 static void
 gtk_file_chooser_button_show_all (GtkWidget *widget)
 {
   gtk_widget_show (widget);
 }
 
-
 static void
 gtk_file_chooser_button_hide_all (GtkWidget *widget)
 {
   gtk_widget_hide (widget);
 }
 
+static void
+gtk_file_chooser_button_show (GtkWidget *widget)
+{
+  GtkFileChooserButtonPrivate *priv;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
+
+  if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show)
+    (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show) (widget);
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)))
+    gtk_widget_show (priv->dialog);
+}
+
+static void
+gtk_file_chooser_button_hide (GtkWidget *widget)
+{
+  GtkFileChooserButtonPrivate *priv;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
+
+  gtk_widget_hide (priv->dialog);
+
+  if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide)
+    (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide) (widget);
+}
 
 static gboolean
 gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
                                           gboolean   group_cycling)
 {
-  GtkFileChooserButton *button;
+  GtkFileChooserButtonPrivate *priv;
 
-  button = GTK_FILE_CHOOSER_BUTTON (widget);
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
 
-  switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->priv->dialog)))
+  switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
     {
     case GTK_FILE_CHOOSER_ACTION_OPEN:
     case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
-      gtk_widget_grab_focus (button->priv->button);
+      gtk_widget_grab_focus (priv->button);
       break;
     case GTK_FILE_CHOOSER_ACTION_SAVE:
     case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
-      gtk_widget_grab_focus (button->priv->entry);
+      gtk_widget_grab_focus (priv->entry);
       break;
     }
 
   return TRUE;
 }
 
+/* Changes the icons wherever it is needed */
+static void
+change_icon_theme (GtkFileChooserButton *button)
+{
+  GtkSettings *settings;
+  gint width, height;
+
+  settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
+
+  if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_SMALL_TOOLBAR,
+                                        &width, &height))
+    button->priv->icon_size = MAX (width, height);
+  else
+    button->priv->icon_size = FALLBACK_ICON_SIZE;
+
+  update_icons (button);
+}
+
+/* Callback used when a GtkSettings value changes */
+static void
+settings_notify_cb (GObject    *object,
+                   GParamSpec *pspec,
+                   gpointer    user_data)
+{
+  const char *name;
+
+  name = g_param_spec_get_name (pspec);
+
+  if (strcmp (name, "gtk-icon-theme-name") == 0
+      || strcmp (name, "gtk-icon-sizes") == 0)
+    change_icon_theme (user_data);
+}
+
+/* Installs a signal handler for GtkSettings so that we can monitor changes in
+ * the icon theme.
+ */
+static void
+check_icon_theme (GtkFileChooserButton *button)
+{
+  GtkSettings *settings;
+
+  if (button->priv->settings_signal_id)
+    return;
+
+  if (gtk_widget_has_screen (GTK_WIDGET (button)))
+    {
+      settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
+      button->priv->settings_signal_id = g_signal_connect (settings, "notify",
+                                                          G_CALLBACK (settings_notify_cb),
+                                                          button);
+
+      change_icon_theme (button);
+    }
+}
+
+static void
+gtk_file_chooser_button_style_set (GtkWidget *widget,
+                                  GtkStyle  *old_style)
+{
+  if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set)
+    (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set) (widget,
+                                                                          old_style);
+
+  if (gtk_widget_has_screen (widget))
+    change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget));
+}
+
+static void
+gtk_file_chooser_button_screen_changed (GtkWidget *widget,
+                                       GdkScreen *old_screen)
+{
+  GtkFileChooserButton *button;
+
+  button = GTK_FILE_CHOOSER_BUTTON (widget);
+
+  if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed)
+    (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed) (widget,
+                                                                               old_screen);
+
+  remove_settings_signal (button, old_screen);
+  check_icon_theme (button); 
+}
+
 
 /* ************************************************************************** *
  *  Public API                                                                *
@@ -614,7 +855,9 @@ gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
 GtkWidget *
 gtk_file_chooser_button_new (const gchar *title)
 {
-  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "title", title, NULL);
+  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+                      "title", title,
+                      NULL);
 }
 
 /**
@@ -632,11 +875,12 @@ GtkWidget *
 gtk_file_chooser_button_new_with_backend (const gchar *title,
                                          const gchar *backend)
 {
-  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "title", title,
-                      "file-system-backend", backend, NULL);
+  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+                      "title", title,
+                      "file-system-backend", backend,
+                      NULL);
 }
 
-
 /**
  * gtk_file_chooser_button_new_with_dialog:
  * @dialog: the #GtkDialog widget to use.
@@ -654,10 +898,11 @@ gtk_file_chooser_button_new_with_dialog (GtkWidget *dialog)
 {
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
 
-  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "dialog", dialog, NULL);
+  return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+                      "dialog", dialog,
+                      NULL);
 }
 
-
 /**
  * gtk_file_chooser_button_set_title:
  * @button: the button widget to modify.
@@ -677,7 +922,6 @@ gtk_file_chooser_button_set_title (GtkFileChooserButton *button,
   g_object_notify (G_OBJECT (button), "title");
 }
 
-
 /**
  * gtk_file_chooser_button_get_title:
  * @button: the button widget to examine.
@@ -697,7 +941,6 @@ gtk_file_chooser_button_get_title (GtkFileChooserButton *button)
   return gtk_window_get_title (GTK_WINDOW (button->priv->dialog));
 }
 
-
 /**
  * gtk_file_chooser_button_set_active:
  * @button: the button widget to modify.
@@ -716,7 +959,6 @@ gtk_file_chooser_button_set_active (GtkFileChooserButton *button,
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->priv->button), is_active);
 }
 
-
 /**
  * gtk_file_chooser_button_get_active:
  * @button: the button widget to examine.
@@ -735,193 +977,411 @@ gtk_file_chooser_button_get_active (GtkFileChooserButton *button)
   return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button->priv->button));
 }
 
+/**
+ * gtk_file_chooser_button_get_width_chars:
+ * @button: the button widget to examine.
+ * 
+ * Retrieves the width in characters of the @button widget's entry and/or label.
+ * 
+ * Returns: an integer width (in characters) that the button will use to size itself.
+ * 
+ * Since: 2.6
+ **/
+gint
+gtk_file_chooser_button_get_width_chars (GtkFileChooserButton *button)
+{
+  g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), -1);
+
+  return gtk_entry_get_width_chars (GTK_ENTRY (button->priv->entry));
+}
+
+/**
+ * gtk_file_chooser_button_set_width_chars:
+ * @button: the button widget to examine.
+ * @n_chars: the new width, in chracters.
+ * 
+ * Sets the width (in characters) that @button will use to @n_chars.
+ * 
+ * Since: 2.6
+ **/
+void
+gtk_file_chooser_button_set_width_chars (GtkFileChooserButton *button,
+                                        gint                  n_chars)
+{
+  g_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
+
+  gtk_entry_set_width_chars (GTK_ENTRY (button->priv->entry), n_chars);
+  gtk_label_set_width_chars (GTK_LABEL (button->priv->label), n_chars);
+  g_object_notify (G_OBJECT (button), "width-chars");
+}
+
 
 /* ******************* *
  *  Utility Functions  *
  * ******************* */
 
+/* Removes the settings signal handler.  It's safe to call multiple times */
 static void
-gtk_file_chooser_button_set_dialog (GObject   *object,
-                                   GtkWidget *dialog)
+remove_settings_signal (GtkFileChooserButton *button,
+                       GdkScreen            *screen)
 {
-  GtkFileChooserButtonPrivate *priv;
-  GtkFilePath *path;
-
-  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
-
-  priv->dialog = dialog;
+  if (button->priv->settings_signal_id)
+    {
+      GtkSettings *settings;
 
-  g_signal_connect (priv->dialog, "delete-event",
-                   G_CALLBACK (dialog_delete_event_cb), object);
-  g_signal_connect (priv->dialog, "response",
-                   G_CALLBACK (dialog_response_cb), object);
+      settings = gtk_settings_get_for_screen (screen);
+      g_signal_handler_disconnect (settings,
+                                  button->priv->settings_signal_id);
+      button->priv->settings_signal_id = 0;
+    }
+}
 
-  /* This is used, instead of the standard delegate, to ensure that signals are only
-   * delegated when the OK button is pressed. */
-  g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, priv->dialog);
-  priv->dialog_folder_changed_id =
-    g_signal_connect (priv->dialog, "current-folder-changed",
-                     G_CALLBACK (dialog_current_folder_changed_cb), object);
-  priv->dialog_file_activated_id =
-    g_signal_connect (priv->dialog, "file-activated",
-                     G_CALLBACK (dialog_file_activated_cb), object);
-  priv->dialog_selection_changed_id =
-    g_signal_connect (priv->dialog, "selection-changed",
-                     G_CALLBACK (dialog_selection_changed_cb), object);
-  g_signal_connect (priv->dialog, "update-preview",
-                   G_CALLBACK (dialog_update_preview_cb), object);
-  g_signal_connect (priv->dialog, "notify",
-                   G_CALLBACK (dialog_notify_cb), object);
-  g_object_add_weak_pointer (G_OBJECT (priv->dialog),
-                            (gpointer *) (&priv->dialog));
+static GtkIconTheme *
+get_icon_theme (GtkWidget *widget)
+{
+  if (gtk_widget_has_screen (widget))
+    return gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
 
-  /* Kinda ugly to set this here... */
-  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (priv->entry),
-                                          _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog)));
-  path = gtk_file_path_new_steal ("/");
-  _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry),
-                                          path);
-  priv->entry_changed_id = g_signal_connect_after (priv->entry, "changed",
-                                                  G_CALLBACK (entry_changed_cb),
-                                                  object);
+  return gtk_icon_theme_get_default ();
 }
 
-
-static gchar *
-get_display_name (gchar *filename)
+static gboolean
+check_if_path_exists (GtkFileSystem     *fs,
+                     const GtkFilePath *path)
 {
-  const gchar *home_dir;
-  gchar *tmp;
-  gsize filename_len, home_dir_len;
+  gboolean path_exists;
+  GtkFilePath *parent_path;
 
-  filename_len = strlen (filename);
+  path_exists = FALSE;
+  parent_path = NULL;
 
-  if (g_file_test (filename, G_FILE_TEST_IS_DIR))
+  if (gtk_file_system_get_parent (fs, path, &parent_path, NULL))
     {
-      tmp = g_new (gchar, filename_len + 2);
-      strcpy (tmp, filename);
-      tmp[filename_len] = '/';
-      tmp[filename_len + 1] = '\0';
-      g_free (filename);
-      filename = tmp;
+      GtkFileFolder *folder;
+    
+      folder = gtk_file_system_get_folder (fs, parent_path, 0, NULL);
+      if (folder)
+       {
+         GtkFileInfo *info;
+       
+         info = gtk_file_folder_get_info (folder, path, NULL);
+         if (info)
+           {
+             path_exists = TRUE;
+             gtk_file_info_free (info);
+           }
+
+         g_object_unref (folder);
+       }
+    
+      gtk_file_path_free (parent_path);
     }
 
-  home_dir = g_get_home_dir ();
-  if (home_dir != NULL)
+  return path_exists;
+}
+
+static void
+update_icons (GtkFileChooserButton *button)
+{
+  GtkFileChooserButtonPrivate *priv;
+  GdkPixbuf *pixbuf;
+  GSList *paths;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+  pixbuf = NULL;
+  paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
+
+  if (paths)
     {
-      home_dir_len = strlen (home_dir);
+      GtkFilePath *path;
+      GtkFileSystem *fs;
 
-      if (strncmp (home_dir, filename, home_dir_len) == 0)
+      path = paths->data;
+      fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+
+      switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
        {
-         tmp = g_build_filename ("~", filename + home_dir_len, NULL);
-         g_free (filename);
-         filename = tmp;
+       case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+         {
+           GtkFileSystemVolume *volume;
+      
+           volume = gtk_file_system_get_volume_for_path (fs, path);
+           if (volume)
+             {
+               GtkFilePath *base_path;
+
+               base_path = gtk_file_system_volume_get_base_path (fs, volume);
+               
+               if (base_path && gtk_file_path_compare (base_path, path) == 0)
+                 pixbuf = gtk_file_system_volume_render_icon (fs, volume,
+                                                              GTK_WIDGET (button),
+                                                              priv->icon_size,
+                                                              NULL);
+
+               if (base_path)
+                 gtk_file_path_free (base_path);
+
+               gtk_file_system_volume_free (fs, volume);
+             }
+         }
+       
+       case GTK_FILE_CHOOSER_ACTION_OPEN:
+         if (!pixbuf)
+           pixbuf = gtk_file_system_render_icon (fs, path, GTK_WIDGET (button),
+                                                 priv->icon_size, NULL);
+         break;
+
+       case GTK_FILE_CHOOSER_ACTION_SAVE:
+         if (check_if_path_exists (fs, path))
+           pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+                                              GTK_STOCK_DIALOG_WARNING,
+                                              priv->icon_size, 0, NULL);
+         else
+           pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+                                              NEW_FILE_ICON_NAME,
+                                              priv->icon_size, 0, NULL);
+         break;
+       case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+         if (check_if_path_exists (fs, path))
+           pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+                                              GTK_STOCK_DIALOG_WARNING,
+                                              priv->icon_size, 0, NULL);
+         else
+           pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+                                              NEW_DIR_ICON_NAME,
+                                              priv->icon_size, 0, NULL);
+         break;
        }
+
+      gtk_file_paths_free (paths);
     }
 
-  return filename;
+  if (!pixbuf)
+    pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+                                      FALLBACK_ICON_NAME,
+                                      priv->icon_size, 0, NULL);
+
+  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->entry_image), pixbuf);
+  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->label_image), pixbuf);
+
+  if (pixbuf)
+    g_object_unref (pixbuf);
 }
 
 
 static void
-update_entry (GtkFileChooserButton *button)
+update_label (GtkFileChooserButton *button)
 {
-  gchar *filename;
+  GtkFileChooserButtonPrivate *priv;
+  gchar *label_text;
+  GSList *paths;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+  paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (button->priv->dialog));
+  label_text = NULL;
 
-  switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->priv->dialog)))
+  if (paths)
     {
-    case GTK_FILE_CHOOSER_ACTION_OPEN:
-    case GTK_FILE_CHOOSER_ACTION_SAVE:
-      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button->priv->dialog));
-      break;
-    case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
-    case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
-      filename = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button->priv->dialog));
-      break;
-    default:
-      g_assert_not_reached ();
-      filename = NULL;
-      break;
-    }
+      GtkFileSystem *fs;
+      GtkFilePath *path;
+      GtkFileSystemVolume *volume;
+    
+      path = paths->data;
 
-  if (filename != NULL)
-    filename = get_display_name (filename);
+      fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
 
-  g_signal_handler_block (button->priv->entry, button->priv->entry_changed_id);
-  if (filename != NULL)
-    gtk_entry_set_text (GTK_ENTRY (button->priv->entry), filename);
-  else
-    gtk_entry_set_text (GTK_ENTRY (button->priv->entry), "");
-  g_signal_handler_unblock (button->priv->entry, button->priv->entry_changed_id);
+      volume = gtk_file_system_get_volume_for_path (fs, path);
+      if (volume)
+       {
+         GtkFilePath *base_path;
+
+         base_path = gtk_file_system_volume_get_base_path (fs, volume);
+         if (base_path && gtk_file_path_compare (base_path, path) == 0)
+           label_text = gtk_file_system_volume_get_display_name (fs, volume);
+
+         if (base_path)
+           gtk_file_path_free (base_path);
+
+         gtk_file_system_volume_free (fs, volume);
+
+         if (label_text)
+           goto out;
+       }
+    
+      if (gtk_file_system_path_is_local (fs, path))
+       {
+         const gchar *home;
+         gchar *tmp;
+         gchar *filename;
+
+          filename = gtk_file_system_path_to_filename (fs, path);
+
+         if (!filename)
+           goto out;
+
+         home = g_get_home_dir ();
+
+         /* Munging for psuedo-volumes and files in the user's home tree */
+         if (home)
+           {
+             if (strcmp (filename, home) == 0)
+               {
+                 label_text = g_strdup (_("Home"));
+                 goto localout;
+               }
+
+             tmp = g_build_filename (home, "Desktop", NULL);
+
+             if (strcmp (filename, tmp) == 0)
+               label_text = g_strdup (_("Desktop"));
+
+             g_free (tmp);
 
-  if (filename != NULL)
-    gtk_label_set_text (GTK_LABEL (button->priv->label), filename);
+             if (label_text)
+               goto out;
+
+             if (g_str_has_prefix (filename, home))
+               {
+                 label_text = g_strconcat ("~", filename + strlen (home), NULL);
+                 goto localout;
+               }
+           }
+
+         if (!label_text)
+           label_text = g_strdup (filename);
+
+        localout:
+         g_free (filename);
+       }
+      else
+       {
+         gchar *uri;
+
+         uri = gtk_file_system_path_to_uri (fs, path);
+
+         if (uri)
+           label_text = uri;
+       }
+
+     out:
+      gtk_file_paths_free (paths);
+    }
+
+  if (label_text)
+    {
+      gtk_label_set_text (GTK_LABEL (priv->label), label_text);
+      g_free (label_text);
+    }
   else
-    gtk_label_set_text (GTK_LABEL (button->priv->label), _(DEFAULT_FILENAME));
-  g_free (filename);
+    gtk_label_set_text (GTK_LABEL (priv->label), _(DEFAULT_FILENAME));
 }
 
-
-static gboolean
-update_dialog (gpointer user_data)
+static void
+update_entry (GtkFileChooserButton *button)
 {
   GtkFileChooserButtonPrivate *priv;
-  const GtkFilePath *folder_path;
-  const gchar *file_part;
-  gchar *full_uri;
+  GSList *paths;
+  gchar *filename;
 
-  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
-  folder_path =
-    _gtk_file_chooser_entry_get_current_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry));
-  file_part =
-    _gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (priv->entry));
-
-  if (folder_path != NULL)
-    full_uri = g_build_filename (gtk_file_path_get_string (folder_path),
-                                file_part, NULL);
-  else if (file_part != NULL)
-    full_uri = g_build_filename ("file://", file_part, NULL);
-  else
-    full_uri = NULL;
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
 
-  if (full_uri != NULL)
-    {
-      gchar *display_name;
+  paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
 
-      display_name = g_filename_from_uri (full_uri, NULL, NULL);
-      if (display_name)
+  if (paths)
+    {
+      GtkFileSystem *fs;
+      GtkFilePath *path;
+    
+      path = paths->data;
+      fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+    
+      if (gtk_file_system_path_is_local (fs, path))
        {
-         display_name = get_display_name (display_name);
-         gtk_label_set_text (GTK_LABEL (priv->label), display_name);
-         g_free (display_name);
+         filename = gtk_file_system_path_to_filename (fs, path);
+
+         if (filename)
+           {
+             const gchar *home;
+             gchar *tmp;
+
+             if (g_file_test (filename, G_FILE_TEST_IS_DIR))
+               {
+                 tmp = g_strconcat (filename, "/", NULL);
+                 g_free (filename);
+                 filename = tmp;
+               }
+
+             home = g_get_home_dir ();
+
+             if (home && g_str_has_prefix (filename, home))
+               {
+                 tmp = g_strconcat ("~", filename + strlen (home), NULL);
+                 g_free (filename);
+                 filename = tmp;
+               }
+           }
        }
+      else
+       filename = gtk_file_system_path_to_uri (fs, path);
     }
   else
+    filename = NULL;
+
+  if (filename)
     {
-      gtk_label_set_text (GTK_LABEL (priv->label), _(DEFAULT_FILENAME));
+      gchar *entry_text;
+    
+      entry_text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+      g_free (filename);
+
+      gtk_entry_set_text (GTK_ENTRY (priv->entry), entry_text);
+      g_free (entry_text);
     }
+  else
+    gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
+}
+
+static void
+update_dialog (GtkFileChooserButton *button)
+{
+  GtkFileChooserButtonPrivate *priv;
+  GtkFilePath *current_folder;
+  GtkFileSystem *fs;
+  GtkFilePath *folder_part, *full_path;
+  gchar *file_part;
+  const gchar *text;
+  GtkFilePath *base_path;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+  file_part = NULL;
+  folder_part = NULL;
+  fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+
+  text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+
+  base_path = gtk_file_path_new_dup ("/");
+  gtk_file_system_parse (fs, base_path, text, &folder_part, &file_part, NULL);
+  gtk_file_path_free (base_path);
 
   switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
     {
     case GTK_FILE_CHOOSER_ACTION_OPEN:
-      if (folder_path != NULL)
+      gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+      if (folder_part)
        {
-         GtkFileSystem *fs;
          GtkFileFolder *folder;
-         GtkFilePath *full_path;
          GtkFileInfo *info;
 
-         fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
-         folder = gtk_file_system_get_folder (fs, folder_path,
+         folder = gtk_file_system_get_folder (fs, folder_part,
                                               GTK_FILE_INFO_IS_FOLDER, NULL);
 
-         full_path = gtk_file_system_make_path (fs, folder_path, file_part, NULL);
+         full_path = gtk_file_system_make_path (fs, folder_part, file_part, NULL);
          info = gtk_file_folder_get_info (folder, full_path, NULL);
 
          /* Entry contents don't exist. */
          if (info == NULL)
            _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
-                                                      folder_path, NULL);
+                                                      folder_part, NULL);
          /* Entry contents are a folder */
          else if (gtk_file_info_get_is_folder (info))
            _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
@@ -930,64 +1390,55 @@ update_dialog (gpointer user_data)
          else
            _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog),
                                           full_path, NULL);
-         
+
          if (info)
            gtk_file_info_free (info);
+
          gtk_file_path_free (full_path);
        }
-      else
-       g_free (full_uri);
       break;
     case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
-      if (folder_path != NULL)
+      gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+      if (folder_part)
        {
-         GtkFileSystem *fs;
-         GtkFilePath *full_path;
-
-         fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
-         full_path = gtk_file_system_make_path (fs, folder_path, file_part, NULL);
+         full_path = gtk_file_system_make_path (fs, folder_part, file_part, NULL);
 
          /* Entry contents don't exist. */
-         if (full_path != NULL)
+         if (full_path)
            _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog),
                                           full_path, NULL);
          else
            _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
-                                                      folder_path, NULL);
+                                                      folder_part, NULL);
 
          gtk_file_path_free (full_path);
        }
-      else
-       g_free (full_uri);
       break;
 
     case GTK_FILE_CHOOSER_ACTION_SAVE:
     case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
-      if (folder_path != NULL)
-       _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
-                                                  folder_path, NULL);
+      gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+      if (folder_part)
+       {
+         current_folder = _gtk_file_chooser_get_current_folder_path (GTK_FILE_CHOOSER (priv->dialog));
+
+         if (!current_folder ||
+             gtk_file_path_compare (current_folder, folder_part) != 0)
+           {
+             _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
+                                                        folder_part, NULL);
+             g_signal_emit_by_name (button, "current-folder-changed");
+           }
+
+         if (current_folder)
+           gtk_file_path_free (current_folder);
+       }
 
       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (priv->dialog),
                                         file_part);
-      g_free (full_uri);
+      g_signal_emit_by_name (button, "selection-changed");
       break;
     }
-  
-  priv->update_id = 0;
-  return FALSE;
-}
-
-static gboolean
-update_dialog_idle (gpointer user_data)
-{
-  gboolean result;
-
-  GDK_THREADS_ENTER ();
-  result = update_dialog (user_data);
-  GDK_THREADS_LEAVE ();
-
-  return result;
-
 }
 
 /* ************************ *
@@ -1001,7 +1452,6 @@ dialog_current_folder_changed_cb (GtkFileChooser *dialog,
   g_signal_emit_by_name (user_data, "current-folder-changed");
 }
 
-
 static void
 dialog_file_activated_cb (GtkFileChooser *dialog,
                          gpointer        user_data)
@@ -1009,15 +1459,31 @@ dialog_file_activated_cb (GtkFileChooser *dialog,
   g_signal_emit_by_name (user_data, "file-activated");
 }
 
-
 static void
 dialog_selection_changed_cb (GtkFileChooser *dialog,
                             gpointer        user_data)
 {
+  GtkFileChooserButtonPrivate *priv;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+  g_signal_handler_block (priv->entry, priv->entry_changed_id);
   update_entry (user_data);
-  g_signal_emit_by_name (user_data, "selection-changed");
+  g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
+  update_icons (user_data);
+  update_label (user_data);
 }
 
+static void
+dialog_selection_changed_proxy_cb (GtkFileChooser *dialog,
+                                  gpointer        user_data)
+{
+  GtkFileChooserButtonPrivate *priv;
+
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+  g_signal_emit_by_name (user_data, "selection-changed");
+}
 
 static void
 dialog_update_preview_cb (GtkFileChooser *dialog,
@@ -1026,7 +1492,6 @@ dialog_update_preview_cb (GtkFileChooser *dialog,
   g_signal_emit_by_name (user_data, "update-preview");
 }
 
-
 static void
 dialog_notify_cb (GObject    *dialog,
                  GParamSpec *pspec,
@@ -1040,7 +1505,6 @@ dialog_notify_cb (GObject    *dialog,
     g_object_notify (user_data, pspec->name);
 }
 
-
 static gboolean
 dialog_delete_event_cb (GtkWidget *dialog,
                        GdkEvent  *event,
@@ -1051,7 +1515,6 @@ dialog_delete_event_cb (GtkWidget *dialog,
   return TRUE;
 }
 
-
 static void
 dialog_response_cb (GtkFileChooser *dialog,
                    gint            response,
@@ -1063,7 +1526,11 @@ dialog_response_cb (GtkFileChooser *dialog,
 
   if (response == GTK_RESPONSE_ACCEPT)
     {
+      g_signal_handler_block (priv->entry, priv->entry_changed_id);
       update_entry (user_data);
+      g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
+      update_label (user_data);
+      update_icons (user_data);
 
       g_signal_emit_by_name (user_data, "current-folder-changed");
       g_signal_emit_by_name (user_data, "selection-changed");
@@ -1110,7 +1577,7 @@ button_toggled_cb (GtkToggleButton *real_button,
       g_signal_handler_block (priv->dialog,
                              priv->dialog_file_activated_id);
       g_signal_handler_block (priv->dialog,
-                             priv->dialog_selection_changed_id);
+                             priv->dialog_selection_changed_proxy_id);
       gtk_widget_set_sensitive (priv->entry, FALSE);
       gtk_window_present (GTK_WINDOW (priv->dialog));
     }
@@ -1121,13 +1588,12 @@ button_toggled_cb (GtkToggleButton *real_button,
       g_signal_handler_unblock (priv->dialog,
                                priv->dialog_file_activated_id);
       g_signal_handler_unblock (priv->dialog,
-                               priv->dialog_selection_changed_id);
+                               priv->dialog_selection_changed_proxy_id);
       gtk_widget_set_sensitive (priv->entry, TRUE);
       gtk_widget_hide (priv->dialog);
     }
 }
 
-
 static void
 button_notify_active_cb (GObject    *real_button,
                         GParamSpec *pspec,
@@ -1137,26 +1603,57 @@ button_notify_active_cb (GObject    *real_button,
 }
 
 
-/* Ensure the button height == entry height */
-static void
-entry_size_allocate_cb (GtkWidget     *entry,
-                       GtkAllocation *allocation,
-                       gpointer       user_data)
+static gboolean
+update_idler (gpointer user_data)
 {
-  gtk_widget_set_size_request (user_data, -1, allocation->height);
-}
+  GtkFileChooserButtonPrivate *priv;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
 
+  priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+  if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry),
+                                         NULL, NULL))
+    {
+      g_signal_handler_block (priv->dialog,
+                             priv->dialog_selection_changed_id);
+      update_dialog (user_data);
+      g_signal_handler_unblock (priv->dialog,
+                               priv->dialog_selection_changed_id);
+      update_icons (user_data);
+      update_label (user_data);
+      priv->update_id = 0;
+      retval = FALSE;
+    }
+  else
+    retval = TRUE;
+  
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
 
 static void
-entry_changed_cb (GtkEditable *chooser_entry,
+entry_changed_cb (GtkEditable *editable,
                  gpointer     user_data)
 {
   GtkFileChooserButtonPrivate *priv;
 
   priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
 
-  /* We do this in an idle handler to avoid totally screwing up chooser_entry's
-   * completion */
-  if (priv->update_id != 0)
-    priv->update_id = g_idle_add (update_dialog_idle, user_data);
+  if (priv->update_id)
+    g_source_remove (priv->update_id);
+
+  priv->update_id = g_idle_add_full (G_PRIORITY_LOW, update_idler,
+                                    user_data, NULL);
+}
+
+/* Ensure the button height == entry height */
+static void
+entry_size_allocate_cb (GtkWidget     *entry,
+                       GtkAllocation *allocation,
+                       gpointer       user_data)
+{
+  gtk_widget_set_size_request (user_data, -1, allocation->height);
 }
index ebbad4a17052792dc116e28d1de0b5814eef32b0..780d73cbe8402d8913d6644a6f667e5aee5fbc34 100644 (file)
@@ -80,7 +80,9 @@ void                  gtk_file_chooser_button_set_title        (GtkFileChooserBu
 gboolean              gtk_file_chooser_button_get_active       (GtkFileChooserButton *button);
 void                  gtk_file_chooser_button_set_active       (GtkFileChooserButton *button,
                                                                gboolean              is_active);
-
+gint                  gtk_file_chooser_button_get_width_chars  (GtkFileChooserButton *button);
+void                  gtk_file_chooser_button_set_width_chars  (GtkFileChooserButton *button,
+                                                               gint                  n_chars);
 
 G_END_DECLS
 
index fe60022204dfc9425415d69d83581a86ff4c415d..7ae2fb0b954d37cb501413a6139f71304833ed7a 100644 (file)
 #include "gtkstock.h"
 #include "gtkbindings.h"
 
+#define GTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_LABEL, GtkLabelPrivate))
+
+typedef struct
+{
+  gint width_chars;
+}
+GtkLabelPrivate;
+
 struct _GtkLabelSelectionInfo
 {
   GdkWindow *window;
@@ -71,7 +79,8 @@ enum {
   PROP_MNEMONIC_WIDGET,
   PROP_CURSOR_POSITION,
   PROP_SELECTION_BOUND,
-  PROP_ELLIPSIZE
+  PROP_ELLIPSIZE,
+  PROP_WIDTH_CHARS
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -391,10 +400,10 @@ gtk_label_class_init (GtkLabelClass *class)
    *
    * Note that setting this property to a value other than %PANGO_ELLIPSIZE_NONE 
    * has the side-effect that the label requests only enough space to display the
-   * ellipsis "...". Ellipsizing labels must be packed in a container which 
-   * ensures that the label gets a reasonable size allocated. In particular, 
-   * this means that ellipsizing labels don't work well in notebook tabs, unless
-   * the tab's ::tab-expand property is set to %TRUE.
+   * ellipsis "...". In particular, this means that ellipsizing labels don't
+   * work well in notebook tabs, unless the tab's ::tab-expand property is set
+   * to %TRUE. Other means to set a label's width are
+   * gtk_widget_set_size_request() and gtk_label_set_width_chars().
    *
    * Since: 2.6
    */
@@ -406,6 +415,25 @@ gtk_label_class_init (GtkLabelClass *class)
                                                      PANGO_TYPE_ELLIPSIZE_MODE,
                                                      PANGO_ELLIPSIZE_NONE,
                                                       G_PARAM_READWRITE));
+
+  /**
+   * GtkLabel:width-chars:
+   * 
+   * The desired width of the label, in characters. If this property is set to
+   * %-1, the width will be calculated automatically, otherwise the label will
+   * request either 3 characters or the property value, whichever is greater.
+   * 
+   * Since: 2.6
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_WIDTH_CHARS,
+                                   g_param_spec_int ("width_chars",
+                                                     P_("Width In Chararacters"),
+                                                     P_("The desired width of the label, in characters"),
+                                                     -1,
+                                                     G_MAXINT,
+                                                     -1,
+                                                     G_PARAM_READWRITE));
   
   /*
    * Key bindings
@@ -483,6 +511,8 @@ gtk_label_class_init (GtkLabelClass *class)
   /* copy */
   gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
                                "copy_clipboard", 0);
+                               
+  g_type_class_add_private (class, sizeof (GtkLabelPrivate));
 }
 
 static void 
@@ -527,6 +557,9 @@ gtk_label_set_property (GObject      *object,
     case PROP_ELLIPSIZE:
       gtk_label_set_ellipsize (label, g_value_get_enum (value));
       break;
+    case PROP_WIDTH_CHARS:
+      gtk_label_set_width_chars (label, g_value_get_int (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -595,6 +628,9 @@ gtk_label_get_property (GObject     *object,
     case PROP_ELLIPSIZE:
       g_value_set_enum (value, label->ellipsize);
       break;
+    case PROP_WIDTH_CHARS:
+      g_value_set_enum (value, gtk_label_get_width_chars (label));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -605,8 +641,13 @@ gtk_label_get_property (GObject     *object,
 static void
 gtk_label_init (GtkLabel *label)
 {
+  GtkLabelPrivate *priv;
+
   GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
-  
+
+  priv = GTK_LABEL_GET_PRIVATE (label);
+  priv->width_chars = -1;
+
   label->label = NULL;
 
   label->jtype = GTK_JUSTIFY_LEFT;
@@ -1355,6 +1396,52 @@ gtk_label_get_ellipsize (GtkLabel *label)
   return label->ellipsize;
 }
 
+/**
+ * gtk_label_set_width_chars:
+ * @label: a #GtkLabel
+ * @n_chars: the new desired width, in characters.
+ * 
+ * Sets the desired width in characters of @label to @n_chars.
+ * 
+ * Since: 2.6
+ **/
+void
+gtk_label_set_width_chars (GtkLabel *label,
+                          gint      n_chars)
+{
+  GtkLabelPrivate *priv;
+
+  g_return_if_fail (GTK_IS_LABEL (label));
+
+  priv = GTK_LABEL_GET_PRIVATE (label);
+
+  if (priv->width_chars != n_chars)
+    {
+      priv->width_chars = n_chars;
+      g_object_notify (G_OBJECT (label), "width-chars");
+      gtk_widget_queue_resize (GTK_WIDGET (label));
+    }
+}
+
+/**
+ * gtk_label_get_width_chars:
+ * @label: a #GtkLabel
+ * 
+ * Retrieves the desired width of @label, in characters. See
+ * gtk_label_set_width_chars().
+ * 
+ * Return value: the width of a label in characters.
+ * 
+ * Since: 2.6
+ **/
+gint
+gtk_label_get_width_chars (GtkLabel *label)
+{
+  g_return_val_if_fail (GTK_IS_LABEL (label), -1);
+
+  return GTK_LABEL_GET_PRIVATE (label)->width_chars;
+}
+
 /**
  * gtk_label_set_line_wrap:
  * @label: a #GtkLabel
@@ -1624,6 +1711,7 @@ gtk_label_size_request (GtkWidget      *widget,
                        GtkRequisition *requisition)
 {
   GtkLabel *label;
+  GtkLabelPrivate *priv;
   gint width, height;
   PangoRectangle logical_rect;
   GtkWidgetAuxInfo *aux_info;
@@ -1632,6 +1720,7 @@ gtk_label_size_request (GtkWidget      *widget,
   g_return_if_fail (requisition != NULL);
   
   label = GTK_LABEL (widget);
+  priv = GTK_LABEL_GET_PRIVATE (widget);
 
   /*  
    * If word wrapping is on, then the height requisition can depend
@@ -1657,7 +1746,7 @@ gtk_label_size_request (GtkWidget      *widget,
   pango_layout_get_extents (label->layout, NULL, &logical_rect);
   aux_info = _gtk_widget_get_aux_info (widget, FALSE);
 
-  if (label->ellipsize)
+  if (label->ellipsize || priv->width_chars > 0)
     {
       PangoContext *context;
       PangoFontMetrics *metrics;
@@ -1670,7 +1759,7 @@ gtk_label_size_request (GtkWidget      *widget,
       char_width = pango_font_metrics_get_approximate_char_width (metrics);
       pango_font_metrics_unref (metrics);
 
-      width += (PANGO_PIXELS (char_width) * 3);
+      width += (PANGO_PIXELS (char_width) * MAX (priv->width_chars, 3));
     }
   else
     {
index ef2d254ab5615a1b83bc610d1997fb23da3c1e8a..9d71cd0b0a30d1f572b25edb681814ebc2d63a6b 100644 (file)
@@ -132,6 +132,9 @@ GtkJustification gtk_label_get_justify            (GtkLabel         *label);
 void     gtk_label_set_ellipsize                 (GtkLabel         *label,
                                                   PangoEllipsizeMode mode);
 PangoEllipsizeMode gtk_label_get_ellipsize        (GtkLabel         *label);
+void     gtk_label_set_width_chars               (GtkLabel         *label,
+                                                  gint              n_chars);
+gint     gtk_label_get_width_chars                (GtkLabel         *label);
 void     gtk_label_set_pattern                    (GtkLabel         *label,
                                                   const gchar      *pattern);
 void     gtk_label_set_line_wrap                  (GtkLabel         *label,
index f23e825c6a39b6e14d68bee729aae88c52937288..b3d7c26793f96914ca4201b2ad0a297fe9fde93d 100644 (file)
@@ -24,6 +24,7 @@ testfilechooserbutton
 testgtk
 testicontheme
 testiconview
+testimage
 testinput
 testmenus
 testmerge
index d453e0f54db782fc10c1a25aa9d7de1c8de3e62a..cbf3eaea87034c9595ee5b89584a04ad95d8c359 100644 (file)
@@ -56,7 +56,7 @@ chooser_current_folder_changed_cb (GtkFileChooser *chooser, gpointer user_data)
 
   folder = gtk_file_chooser_get_current_folder (chooser);
   filename = gtk_file_chooser_get_filename (chooser);
-  g_message ("%s:%s:\n`%s`\n\tFolder: `%s'\n\tFilename: `%s'", G_STRFUNC, G_STRLOC,
+  g_message ("%s::current-folder-changed\n\tFolder: `%s'\n\tFilename: `%s'\nDone.\n",
             G_OBJECT_TYPE_NAME (chooser), folder, filename);
   g_free (folder);
   g_free (filename);
@@ -66,16 +66,12 @@ chooser_current_folder_changed_cb (GtkFileChooser *chooser, gpointer user_data)
 static void
 chooser_selection_changed_cb (GtkFileChooser *chooser, gpointer user_data)
 {
-  GSList *selection;
+  gchar *filename;
 
-  g_message ("%s:%s:\n`%s` Selection:", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser));
-  for (selection = gtk_file_chooser_get_filenames (chooser); selection != NULL;
-       selection = g_slist_remove_link (selection, selection))
-    {
-      g_print ("`%s'\n", (const gchar *) selection->data);
-      g_free (selection->data);
-    }
-  g_print ("Done.\n");
+  filename = gtk_file_chooser_get_filename (chooser);
+  g_message ("%s::selection-changed\n\tSelection:`%s'\nDone.\n",
+            G_OBJECT_TYPE_NAME (chooser), filename);
+  g_free (filename);
 }
 
 
@@ -86,7 +82,8 @@ chooser_file_activated_cb (GtkFileChooser *chooser, gpointer user_data)
 
   folder = gtk_file_chooser_get_current_folder (chooser);
   filename = gtk_file_chooser_get_filename (chooser);
-  g_message ("%s:%s:\n`%s`\nFolder: `%s'\nFilename: `%s'", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser), folder, filename);
+  g_message ("%s::file-activated\n\tFolder: `%s'\n\tFilename: `%s'\nDone.\n",
+            G_OBJECT_TYPE_NAME (chooser), folder, filename);
   g_free (folder);
   g_free (filename);
 }
@@ -98,17 +95,17 @@ chooser_update_preview_cb (GtkFileChooser *chooser, gpointer user_data)
   gchar *filename;
 
   filename = gtk_file_chooser_get_preview_filename (chooser);
-  g_message ("%s:%s:\n`%s`\nPreview Filename: `%s'", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser), filename);
+  g_message ("%s::update-preview\n\tPreview Filename: `%s'\nDone.\n",
+            G_OBJECT_TYPE_NAME (chooser), filename);
   g_free (filename);
 }
 
-
 int
 main (int argc, char *argv[])
 {
-  GtkWidget *win, *vbox, *frame, *alignment, *group_box, *hbox, *label, *chooser, *button;
+  GtkWidget *win, *vbox, *frame, *alignment, *group_box;
+  GtkWidget *hbox, *label, *chooser, *button;
   GtkSizeGroup *label_group;
-
   gtk_init (&argc, &argv);
 
   /* to test rtl layout, set RTL=1 in the environment */
@@ -138,15 +135,80 @@ main (int argc, char *argv[])
   gtk_container_add (GTK_CONTAINER (alignment), group_box);
 
   hbox = gtk_hbox_new (FALSE, 12);
-  gtk_container_add (GTK_CONTAINER (group_box), hbox);
+  gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
 
   label = gtk_label_new_with_mnemonic ("_Open:");
   gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
-  chooser = gtk_file_chooser_button_new_with_backend ("Select A File - testfilechooserbutton",
-                                                     "gtk+");
+  chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+  g_signal_connect (chooser, "current-folder-changed",
+                   G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+  g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+  g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+  g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+  gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+  button = gtk_button_new_with_label ("Properties...");
+  g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new_with_mnemonic ("Select _Folder:");
+  gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+  chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+  gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+  g_signal_connect (chooser, "current-folder-changed",
+                   G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+  g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+  g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+  g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+  gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+  button = gtk_button_new_with_label ("Properties...");
+  g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new_with_mnemonic ("_Save:");
+  gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+  chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+  gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+  g_signal_connect (chooser, "current-folder-changed",
+                   G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+  g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+  g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+  g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+  gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+  button = gtk_button_new_with_label ("Properties...");
+  g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new_with_mnemonic ("_Create Folder:");
+  gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+  chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+  gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
   gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
   g_signal_connect (chooser, "current-folder-changed",
                    G_CALLBACK (chooser_current_folder_changed_cb), NULL);